// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.Globalization;
using System.Xml;

namespace BlueOnionSoftware.Bloget
{
    internal class XmlRpcValue
    {
        private readonly object value;

        internal XmlRpcValue()
        {
        }

        internal XmlRpcValue(int intValue)
        {
            value = intValue;
        }

        internal XmlRpcValue(bool boolValue)
        {
            value = boolValue;
        }

        internal XmlRpcValue(string stringValue)
        {
            Throw.IfNull(stringValue, "stringValue"); // OK to be empty
            value = stringValue;
        }

        internal XmlRpcValue(double doubleValue)
        {
            value = doubleValue;
        }

        internal XmlRpcValue(DateTime dateTimeValue)
        {
            value = dateTimeValue;
        }

        internal XmlRpcValue(byte[] byteArrayValue)
        {
            Throw.IfNull(byteArrayValue, "byteArrayValue");
            value = byteArrayValue;
        }

        internal XmlRpcValue(XmlRpcStruct structValue)
        {
            if (structValue == null)
            {
                throw new ArgumentNullException("structValue");
            }

            value = structValue;
        }

        internal XmlRpcValue(XmlRpcArray arrayValue)
        {
            Throw.IfNull(arrayValue, "arrayValue");
            value = arrayValue;
        }

        internal object Value
        {
            get { return value; }
        }

        internal void Serialize(XmlWriter writer)
        {
            Throw.IfNull(writer, "writer");
            writer.WriteStartElement("value");
            var valueType = value.GetType();

            if (valueType == typeof (int))
            {
                writer.WriteElementString("int", value.ToString());
            }

            else if (valueType == typeof (bool))
            {
                writer.WriteElementString("boolean", ((bool) value) ? "1" : "0");
            }

            else if (valueType == typeof (double))
            {
                writer.WriteElementString("double", value.ToString());
            }

            else if (valueType == typeof (string))
            {
                writer.WriteElementString("string", value.ToString());
            }

            else if (valueType == typeof (DateTime))
            {
                // It's not iso8601, it's XML-RPC!
                writer.WriteElementString("dateTime.iso8601",
                                          ((DateTime) value).ToString("yyyyMMddTHH:mm:ss", CultureInfo.InvariantCulture));
            }

            else if (valueType == typeof (byte[]))
            {
                var buffer = (byte[]) value;
                writer.WriteStartElement("base64");
                writer.WriteBase64(buffer, 0, buffer.Length);
                writer.WriteEndElement();
            }

            else if (valueType == typeof (XmlRpcStruct))
            {
                ((XmlRpcStruct) value).Serialize(writer);
            }

            else if (valueType == typeof (XmlRpcArray))
            {
                ((XmlRpcArray) value).Serialize(writer);
            }

            writer.WriteEndElement();
        }

        public override string ToString()
        {
            return value.ToString();
        }
    }
}